package com.pimee.support.shiro.session;

import java.io.Serializable;
import java.util.Collection;
import java.util.Date;

import org.apache.shiro.session.Session;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import com.pimee.common.constants.Constants.OnlineStatus;
import com.pimee.service.admin.ISysUserOnlineService;
import com.pimee.support.manager.AsyncManager;
import com.pimee.support.manager.factory.AsyncFactory;

public class PmRedisSessionDAO extends RedisSessionDAO {

	/**
	 * 上次同步数据库的时间戳
	 */
	private static final String LAST_SYNC_DB_TIMESTAMP = RedisSessionDAO.class.getName() + ":LAST_SYNC_DB_TIMESTAMP";
	/**
	 * 同步session到数据库的周期 单位为毫秒（默认1分钟）
	 */
	@Value("${shiro.session.dbSyncPeriod}")
	private int dbSyncPeriod;

	@Autowired
	private ISysUserOnlineService onlineService;

	@Override
	public Collection<Session> getActiveSessions() {
		return super.getActiveSessions();
	}

	/**
	 * 根据会话ID获取会话 先从缓存中获取session
	 * 
	 * @param sessionId
	 *            会话ID
	 * @return Session
	 */
	@Override
	public Session readSession(Serializable sessionId) {
		Object obj = super.readSession(sessionId);
		OnlineSession session = (OnlineSession) obj;
		return session;
	}

	/**
	 * 当会话过期/停止（如用户退出时）属性等会调用
	 */
	@Override
	public void delete(Session session) {
		OnlineSession onlineSession = (OnlineSession) session;
		if (null == onlineSession) {
			return;
		}
		super.delete(onlineSession);
		onlineSession.setStatus(OnlineStatus.OFFLINE);
		onlineService.deleteOnlineBySessionId(String.valueOf(onlineSession.getId()));
	}

	/**
	 * 更新会话；如更新会话最后访问时间/停止会话/设置超时时间/设置移除属性等会调用
	 */
	public void syncToDb(OnlineSession onlineSession) {
		Date lastSyncTimestamp = (Date) onlineSession.getAttribute(LAST_SYNC_DB_TIMESTAMP);
		if (lastSyncTimestamp != null) {
			boolean needSync = true;
			long deltaTime = onlineSession.getLastAccessTime().getTime() - lastSyncTimestamp.getTime();
			if (deltaTime < dbSyncPeriod * 60 * 1000) {
				// 时间差不足 无需同步
				needSync = false;
			}
			boolean isGuest = onlineSession.getUserId() == null || onlineSession.getUserId() == 0L;

			// session 数据变更了 同步
			if (isGuest == false && onlineSession.isAttributeChanged()) {
				needSync = true;
			}

			if (needSync == false) {
				return;
			}
		}
		onlineSession.setAttribute(LAST_SYNC_DB_TIMESTAMP, onlineSession.getLastAccessTime());
		// 更新完后 重置标识
		if (onlineSession.isAttributeChanged()) {
			onlineSession.resetAttributeChanged();
		}
		AsyncManager.me().execute(AsyncFactory.syncSessionToDb(onlineSession));
	}

}